﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// filters  by replacing every pixel by the difference of the maximum and minimum in its range  neighborhood. 
    /// 
    /// J = rangefilt(I) returns the array J, where each output pixel contains the range value (maximum value − minimum value)
    /// of the 3-by-3 neighborhood around the corresponding pixel in the input image I. 
    /// The image I can have any dimension. The output image J is the same size as the input image I.
    /// 
    /// J = rangefilt(I, NHOOD) performs range filtering of the input image I where you specify the neighborhood in NHOOD.
    /// NHOOD is a multidimensional array of zeros and ones where the nonzero elements specify the neighborhood for the range 
    /// filtering operation. NHOOD's size must be odd in each dimension.
    /// 
    /// By default, rangefilt uses the neighborhood true(3). rangefilt determines the center element of the 
    /// neighborhood by floor((size(NHOOD) + 1)/2). For information about specifying neighborhoods, see Notes.
    /// 
    /// Class Support
    /// 
    /// I can be logical or numeric and must be real and nonsparse.
    /// NHOOD can be logical or numeric and must contain zeros or ones.
    /// 
    /// The output image J is the same class as I, except for signed integer data types. 
    /// The output class for signed data types is the corresponding unsigned integer data type. 
    /// For example, if the class of I is int8, then the class of J is uint8.
    /// </summary>
    public class rangefilt : BaseImageFilter
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="rangefilt"/> class.
        /// </summary>
        public rangefilt()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="rangefilt"/> class.
        /// </summary>
        /// <param name="_rangefilt">The _rangefilt.</param>
        internal rangefilt(rangefilt _rangefilt)
        {
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmapCloned = (UnsafeBitmap)_bitmap.Clone();
            int nWidth = _bitmap.Width;
            int nHeight = _bitmap.Height;
            int x = 0;
            int y = 0;
            for (y = 2; y < nHeight - 2; y++)
            {
                for (x = 2; x < nWidth - 2; x++)
                {
                    int nMin = int.MaxValue;
                    int nMax = int.MinValue;

                    for (int ky = 0; ky < 3; ky++)
                    {
                        for (int kx = 0; kx < 3; kx++)
                        {
                            int nValue = ColorFunctions.ToIntRGB(bitmapCloned.GetPixel(x - 1 + kx, y - 1 + ky));
                            if (nValue > nMax) nMax = nValue;
                            if (nValue < nMin) nMin = nValue;
                        }
                    }

                    _bitmap.SetPixel(x, y, Color.FromArgb(255, Color.FromArgb((int)Math.Abs(nMin - nMax))));
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new rangefilt(this);
        }
    }
}
